package lianxi;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * 1 使用三种方式获取运行时类
 * 
 * 2 使用反射创建类对象
 * 
 * 3 使用反射 设置/获取 指定变量的值
 * 
 * 4 使用反射 调用指定方法
 * 
 * 5 使用指定 构造方法创建对象
 * 
 * 6 创建一个方法,参数列表使用一个可变长参数
 * 
 * 7 获取String类中 所有方法的 修饰符 , 返回值类型 , 方法名 , 参数列表中所有参数的数据类型
 * 
 * @author yingfing
 * @date 2020年10月3日 @time 上午8:51:20
 */
public class Reflect_LianXi {

	public static void main(String[] args) throws Exception {
		test1();
		test2();
		test3();
		test4();
		test5();
		test6(1, 2, 3, 4, 5, 6);
		test7();
	}

	/**
	 * 1 使用三种方式获取运行时类
	 * 
	 * @throws Exception
	 */
	public static void test1() throws Exception {

		// 第一种 : 通过类的静态方法 forName
		// 通过类全名的字符串获取
		Class class1 = Class.forName("lianxi.Exercise");

		// 第二种 : 通过每个类的 class 属性获取
		Class class2 = Exercise.class;

		// 第三种 : 通过对象的 getClass() 方法获取
		Exercise exercise = new Exercise();
		Class classs3 = exercise.getClass();
		System.out.println("1 使用三种方式获取运行时类 : " + class1 + " \n" + class2 + " \n" + classs3);
	}

	/**
	 * 2 使用反射创建类对象
	 * 
	 * @throws Exception
	 */
	public static void test2() throws Exception {

		Class class1 = Class.forName("lianxi.Exercise");
		// 通过 newInstance 创建对象
		Exercise e1 = (Exercise) class1.newInstance();
		System.out.println("2 使用反射创建类对象 : " + e1);
	}

	/**
	 * 3 使用反射 设置/获取 指定变量的值
	 * 
	 * @throws Exception
	 */
	public static void test3() throws Exception {

		Class class1 = Class.forName("lianxi.Exercise");
		Exercise e = (Exercise) class1.newInstance();
		Field f = class1.getDeclaredField("id");
		// 打破封装性
		f.setAccessible(true);
		// set() 方法设置变量的值
		f.set(e, 4);
		System.out.println("3 使用反射 设置/获取 指定变量的值 : " + e.getId());
	}

	/**
	 * 4 使用反射 调用指定方法
	 * 
	 * @throws Exception
	 */
	public static void test4() throws Exception {

		Class class1 = Class.forName("lianxi.Exercise");
		Method method = class1.getDeclaredMethod("test");
		// 打破方法封装性
		method.setAccessible(true);

		// 创建对象
		Object o = class1.newInstance();

		// 调用方法
		method.invoke(o);
	}

	/**
	 * 5 使用指定 构造方法创建对象
	 * 
	 * @throws Exception
	 */
	public static void test5() throws Exception {

		Class class1 = Class.forName("lianxi.Exercise");

		// 获取指定的构造方法
		Constructor constructor = class1.getDeclaredConstructor(int.class, String.class, String.class);
		// 打破构造方法封装性
		constructor.setAccessible(true);
		Object object = constructor.newInstance(1, "张三", "zhang3");
		System.out.println("5 使用指定 构造方法创建对象 : " + object);
	}

	/**
	 * 6 创建一个方法,参数列表使用一个可变长参数
	 * 
	 * @param arr
	 */
	public static void test6(int... arr) {

		for (int i : arr) {
			System.out.print(i + "  ");
		}
		System.out.println();
		System.out.println("6 创建一个方法,参数列表使用一个可变长参数 ");
	}

	/**
	 * 7 获取String类中 所有方法的 修饰符 , 返回值类型 , 方法名 , 参数列表中所有参数的数据类型
	 * 
	 * @throws Exception
	 */
	public static void test7() throws Exception {

		System.out.println("7 获取String类中 所有方法的 修饰符 , 返回值类型 , 方法名 , 参数列表中所有参数的数据类型");

		Class class1 = Class.forName("java.lang.String");
		// 所有方法
		Method[] ms = class1.getDeclaredMethods();
		// 每一个方法
		for (Method method : ms) {
			// 修饰符
			System.out.print(Modifier.toString(method.getModifiers()) + " ");
			// 返回值类型
			Class returnType = method.getReturnType();
			System.out.print(returnType.getSimpleName() + " ");
			// 方法名
			System.out.print(method.getName() + " ( ");
			// 参数列表
			Class[] parameterTypes = method.getParameterTypes();
			for (Class parameterType : parameterTypes) {
				System.out.print(parameterType.getSimpleName() + " , ");
			}
			System.out.println(" ) ");
		}
	}
}

class Exercise {

	private int id;
	private String username;
	private String password;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Exercise() {
		super();
	}

	private Exercise(int id, String username, String password) {
		super();
		this.id = id;
		this.username = username;
		this.password = password;
	}

	@Override
	public String toString() {
		return "Exercise [id=" + id + ", username=" + username + ", password=" + password + "]";
	}

	private void test() {
		System.out.println("4 通过反射调用的方法 ! ");
	}
}
